package com.lottemall.cart.serveice;

import com.lottemall.auth.entity.UserInfo;
import com.lottemall.cart.interceptor.UserInterceptor;
import com.lottemall.cart.pojo.Cart;
import com.lottemall.common.enums.ExceptionEnume;
import com.lottemall.common.exception.LtException;
import com.lottemall.common.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/***
 * 购物车业务层
 *
 * 购物车结构是一个双层Map    Map<String,Map<String,String>>(第一个key是用户Id,第二个是商品skuid,然后value是sku的json详情)
 */
@Service
public class CartService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //即将存入redis的key前缀
    private static final String KEY_PREFIX = "cart:uid";

    /**
     * 添加sku商品到购物车
     *
     * @param cart
     */
    public void addCart(Cart cart) {
        //获取用户 (这里为什么可以得到用户信息，因为从拦截器走到这里的是同一个线程，是一定可以取出来的)
        UserInfo userInfo = UserInterceptor.getUser();
        //得到key
        String key = KEY_PREFIX + userInfo.getId();
        //hashkey   商品id
        String hashkey = cart.getSkuId().toString();
        //记录num
        Integer num = cart.getNum();

        //这个也可以用于判断key是否存在，这里事先传入的用户的key是否存在，然后下面判断商品是否存在就方便就不用传入两个key了。
        BoundHashOperations<String, Object, Object> operations = stringRedisTemplate.boundHashOps(key);
        //判断 当前sku商品是否存在
        if (operations.hasKey(hashkey)) {
            //根据商品skuid得到商品json详情
            String jsonCart = operations.get(hashkey).toString();
            //将json字符串转成对象（反序列化）
            cart = JsonUtils.parse(jsonCart, Cart.class);
            //增加数量 (num是用户选择的商品的数量，cart.getNum()是数据库中已有同款的数量)
            cart.setNum(cart.getNum() + num);
        }
        //写回redis
        operations.put(hashkey, JsonUtils.serialize(cart));
    }

    /**
     * 查询当前用户的购物车
     * @return
     */
    public List<Cart> queryCartList() {
        //获取用户 (这里为什么可以得到用户信息，因为从拦截器走到这里的是同一个线程，是一定可以取出来的)
        UserInfo userInfo = UserInterceptor.getUser();
        //得到key
        String key = KEY_PREFIX + userInfo.getId();
        if (!stringRedisTemplate.hasKey(key)){
            //key不存在，返回404
            throw new LtException(ExceptionEnume.CART_NOT_FOUND);
        }
        //获取登录用户的所有数据
        BoundHashOperations<String, Object, Object> operations = stringRedisTemplate.boundHashOps(key);
        //得到用户的购物车集合，然后吧字符串转化为对象，然后转化为对象集合
        List<Cart> cartList = operations.values().stream().map(o -> JsonUtils.parse(o.toString(), Cart.class)).collect(Collectors.toList());
        return cartList;
    }

    /**
     * 修改购物车中的商品数量
     * @param skuId
     * @param num 当前用户操作后的数量
     * @return
     */
    public void updateCartNum(Long skuId, Integer num) {
        //获取用户 (这里为什么可以得到用户信息，因为从拦截器走到这里的是同一个线程，是一定可以取出来的)
        UserInfo userInfo = UserInterceptor.getUser();
        //得到key
        String key = KEY_PREFIX + userInfo.getId();
        //得到hashkey(商品id)
        String hashkey = skuId.toString();

        //获取登录用户的所有数据
        BoundHashOperations<String, Object, Object> operations = stringRedisTemplate.boundHashOps(key);
        //判断是否存在
        if (!operations.hasKey(hashkey)){
            throw new LtException(ExceptionEnume.CART_NOT_FOUND);
        }
        //根据商品id查询商品详情
        Cart cart = JsonUtils.parse(operations.get(hashkey).toString(), Cart.class);
        //设置当前商品数量
        cart.setNum(num);
        //写回redis
        operations.put(hashkey, JsonUtils.serialize(cart));
    }

    /**
     * 删除购物车中的商品
     * @param skuId
     */
    public void deleteCart(Long skuId) {
        //获取用户 (这里为什么可以得到用户信息，因为从拦截器走到这里的是同一个线程，是一定可以取出来的)
        UserInfo userInfo = UserInterceptor.getUser();
        //得到key
        String key = KEY_PREFIX + userInfo.getId();
        //删除(注意我们的购物车数据结构是怎样的)
        stringRedisTemplate.opsForHash().delete(key,skuId.toString());
    }
}
